//
//  ExamBranch.m
//  ocdemo
//
//  Created by JIENING ZHANG on 2020/5/9.
//  Copyright © 2020 JIENING ZHANG. All rights reserved.
//

#import "ExamBranch.h"
#import <objc/runtime.h>

@implementation ExamBranch

+ (BOOL)isLeapYear:(int)year {
    
    if(0 == year%400) {
        // 能被400整除的年份是闰年
        return YES;
    }
    
    if(0 == year%100) {
        // 不能被400整除 但是能被100整除的年份是 平年
        return NO;
        
    } else if(0 == year%4) {
        // 不能被100整除，但是能被4整除的年份是 润年
        return YES;
        
    } else {
    
        // 其他的年份是平年
        return NO;
    }
}


+ (int)dayNumOfYear:(int)year month:(int)month {
    int dayNum = 31;
    switch (month) {
        case 4:
        case 6:
        case 9:
        case 11:
            dayNum = 30;
            break;
        case 2:
            dayNum = [ExamBranch isLeapYear:year] ? 29: 28;
        default:
            break;
    }
    
    return dayNum;
}
/**
 2019年1月1日 是周二，以此为基准，计算一个日期对应的星期

 @param year 闭区间[-2000, 4000]
 @param month 1base，[1, 12]
 @param day 1base, [1, 31]
 @return 1base week day [1, 7], -1 if not a valid day
 */
+ (int)computeWeekDayOfYear:(int)year month:(int)month day:(int)day {
    // todo: 计算逻辑
    // 2020年5月9日 是周6，以此为基准，计算一个日期对应的星期，不接受其他的算法，注意做边界异常判断
    // 不合法的日期 返回 -1
    
    if(month<1 || month>12) {
        return -1;
    }
    
    int diffDays = 0;
    for (int yr = 2020; yr != year;) {
        if(yr > year) {
            yr -= 1;
            diffDays -= ([ExamBranch isLeapYear:yr] ? 366 : 365);
        } else {
            diffDays += ([ExamBranch isLeapYear:yr] ? 366 : 365);
            yr += 1;
        }
    }
    
    for (int mn = 5; mn != month;) {
        if(mn > month) {
            mn -= 1;
            diffDays -= [ExamBranch dayNumOfYear:2020 month:mn];
        } else {
            diffDays += [ExamBranch dayNumOfYear:2020 month:mn];
            mn += 1;
        }
    }
    
    diffDays += (day-9);
    
    NSLog(@"diffDays %d", diffDays);
    
    while (diffDays <0) {
        diffDays += 7;
    }
    
    //NSLog(@"diffDays %d", diffDays);
    
    int weekDay = (diffDays + 5)%7; //
    
    NSLog(@"diffDays %d, weekDay %d", diffDays, weekDay+1);
    
    return weekDay+1;
}

// 验证
+ (void)demoLogic {
    for(int y=1999; y<2022; ++y) {
        
        for(int m=2; m<=12; ++m) {
            int dayNum = [ExamBranch dayNumOfYear:y month:m];
            NSLog(@"%d年%d月 dayNum:%d", y, m, dayNum);
            for(int d=26; d<=31; ++d) {
                
                int weekDay = [ExamBranch computeWeekDayOfYear:y month:m day:d];
                
                NSString *weekStr = weekDay<0 ? nil : [NSString stringWithFormat:@"星期%d", weekDay];
                
                NSLog(@"%d年%d月%d日 -> %@", y, m, d, (weekStr ? :@"无效日期"));
                break;
            }
            break;
        }
        //break;
    }
}

@end


//请按照自己的思路实现一个ThreadLocal类，供线程存取线程私有的内容，根据自己思路，用最好的代码来实现。
//ThreadLocal<String> local = new ThreadLocal<>();
//在线程中存取当前线程的内容。
//local.set(“Hello World”);
//local.get()
static char *ThreadLocalKey;
@implementation ThreadLocal

+ (NSMutableDictionary *)sharedMap4Threads {
    static dispatch_once_t onceToken;
    static NSMutableDictionary *instance;
    dispatch_once(&onceToken, ^{
        instance = [NSMutableDictionary dictionary];
    });
    return instance;
}

+ (id)get {
    id val = objc_getAssociatedObject([NSThread currentThread], &ThreadLocalKey);
    if(val && [val isKindOfClass:[NSNull class]]) {
        return nil;
    }
    return nil;
}

+ (void)set:(id) value {
    if(value) {
        objc_setAssociatedObject([NSThread currentThread], &ThreadLocalKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    } else {
        objc_setAssociatedObject([NSThread currentThread], &ThreadLocalKey, [NSNull null], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
}

+ (void)remove {
    objc_setAssociatedObject([NSThread currentThread], &ThreadLocalKey, [NSNull null], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end

@implementation HanoiTower

+ (NSString *)towerName:(int)tid {
    if(tid == 0) {
        return @"A";
    }
    if(tid == 1) {
        return @"B";
    }
    if(tid == 2) {
        return @"C";
    }
    return @"";
}

+ (void)moveHanoiTowerFrom:(int)from to:(int)to numberFrom:(int)numberFrom {
    //①  如果只有 1 个盘子，则不需要利用 B 塔，直接将盘子从 A 移动到 C 。

    //② 如果有 2 个盘子，可以先将盘子 2 上的盘子 1 移动到 B ；将盘子 2 移动到 C ；将盘子 1 移动到 C 。这说明了：可以借助 B 将 2 个盘子从 A 移动到 C ，当然，也可以借助 C 将 2 个盘子从 A 移动到 B 。

    //③ 如果有 3 个盘子，那么根据 2 个盘子的结论，可以借助 C 将盘子 3 上的两个盘子从 A 移动到 B ；将盘子 3 从 A 移动到 C ，A 变成空座；借助 A 座，将 B 上的两个盘子移动到 C 。

    //④ 以此类推，上述的思路可以一直扩展到 n 个盘子的情况，将将较小的 n-1个盘子看做一个整体，也就是我们要求的子问题，以借助 B 塔为例，可以借助空塔 B 将盘子A上面的 n-1 个盘子从 A 移动到 B ；将A 最大的盘子移动到 C ， A 变成空塔；借助空塔 A ，将 B 塔上的 n-2 个盘子移动到 A，将 B 最大的盘子移动到 C， B 变成空塔。。。
    if(numberFrom == 1) {
        NSLog(@"%@->%@", [HanoiTower towerName:from], [HanoiTower towerName:to]);
        return;
    }
    
    int mid=0;
    if(from == mid || to==mid){
        mid += 1;
    }
    if(from == mid || to==mid){
        mid += 1;
    }
    
    //*
    NSLog(@"from %@ mid %@ to %@, numberFrom %d",
          [HanoiTower towerName:from],
          [HanoiTower towerName:mid],
          [HanoiTower towerName:to],
          numberFrom);
    //*/
    
    if (numberFrom == 2) {
        NSLog(@"%@->%@", [HanoiTower towerName:from], [HanoiTower towerName:mid]);
        NSLog(@"%@->%@", [HanoiTower towerName:from], [HanoiTower towerName:to]);
        NSLog(@"%@->%@", [HanoiTower towerName:mid], [HanoiTower towerName:to]);
    } else {
        [HanoiTower moveHanoiTowerFrom:from to:mid numberFrom:numberFrom-1];
        [HanoiTower moveHanoiTowerFrom:from to:to numberFrom:1];
        [HanoiTower moveHanoiTowerFrom:mid to:to numberFrom:numberFrom-1];
    }
}
@end
